package cn.ad.server.web.spring.service.actions;

import cn.ad.server.common.utils.IPUtils;
import cn.ad.server.common.utils.StringUtil;
import cn.ad.server.web.log.IAdServerLogger;
import cn.ad.server.web.spring.model.BidAdRequest;
import cn.ad.server.web.spring.model.BidAdResponse;
import cn.ad.server.web.spring.model.Exchange;
import cn.ad.server.web.spring.model.adview.AdViewBidRequest;
import cn.ad.server.web.spring.model.adview.AdViewOperator;
import cn.ad.server.web.spring.model.bes.AdBesAppInteractionType;
import cn.ad.server.web.spring.model.bes.AdBesConnection;
import cn.ad.server.web.spring.model.bes.BES.BidRequest;
import cn.ad.server.web.spring.model.bes.BES.BidRequest.*;
import cn.ad.server.web.spring.model.bes.BES.BidRequest.CustomizedUserTag.AmsTag;
import cn.ad.server.web.spring.model.bes.BES.BidRequest.Geo.Coordinate;
import cn.ad.server.web.spring.model.bes.BES.BidRequest.Mobile.*;
import cn.ad.server.web.spring.model.bes.BES.BidRequest.Mobile.MobileApp.AppInteractionType;
import cn.ad.server.web.spring.model.bes.BES.BidResponse;
import cn.ad.server.web.spring.model.bes.BES.BidResponse.Ad;
import cn.ad.server.web.spring.model.bes.BESBidRequest;
import cn.ad.server.web.spring.model.bes.BESBidResponse;
import cn.ad.server.web.spring.service.actions.context.BidContext;
import cn.ad.server.web.spring.service.actions.context.IPContext;
import cn.ad.server.web.spring.service.biz.BESImpressionMatchService;
import cn.ad.server.web.utils.WebUtils;
import cn.ad.server.web.utils.WebUtils.DeviceInfo;
import cn.ad.server.biz.internal.AdService;
import cn.ad.server.domain.IPDetail;
import cn.ad.server.domain.enumration.Connection;
import cn.ad.server.domain.enumration.FalconAppInteractionType;
import cn.ad.server.domain.enumration.MUniqueType;
import cn.ad.server.domain.enumration.Operator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 百度Adx接入请求处理
 * 
 * @author wangwei
 *
 */
@Component("action-bid-bes")
public class BESAdRequestAction extends BidAdRequestAction {

	static Logger LOGGER = LoggerFactory.getLogger(BESAdRequestAction.class);

	@Autowired
	private BESImpressionMatchService besImpressionHandler;

	@Autowired
	private IAdServerLogger loggerService;

	@Autowired
	private AdService adService;

	/*
	 * (non-Javadoc)
	 * 
	 * @see cn.ad.server.web.spring.service.actions.
	 * BidAdRequestAction#doRequest(cn.ad.server.web.spring.
	 * model.BidAdRequest)
	 */
	@Override
	BidAdResponse doRequest(BidAdRequest request) {
		try {
			BESBidRequest req = (BESBidRequest) request;
			BidContext context = initBidData(req);
			return doProcess(req, context);
		} finally {
			adService.unbond();
		}
	}

	public BidAdResponse doProcess(BidAdRequest bidAdRequest, BidContext bidContext) {

		BESBidRequest besBidRequest = (BESBidRequest) bidAdRequest;
		BidRequest bidRequest = besBidRequest.buildRequest();
		BESBidResponse besBidResponse = new BESBidResponse();
		BidResponse.Builder responseBuilder = besBidResponse.getBuilder();

		responseBuilder.setId(bidRequest.getId());
		// 处理参数解析异常的处理
		if (bidContext == null) {
			responseBuilder.setId(bidRequest.getId());

			return besBidResponse;
		}

		List<AdSlot> adslotList = bidRequest.getAdslotList();

		for (int i = 0; i < adslotList.size(); i++) {

			BidContext impBidContext = (BidContext) bidContext.clone();
			try {
				impBidContext.setOriginImpression(adslotList.get(i));
				Ad.Builder bidBuiler = besImpressionHandler.handler(adslotList.get(i), impBidContext);
				if (bidBuiler != null) {
					responseBuilder.addAd(bidBuiler);
				}
			} catch (Exception e) {
				LOGGER.error("There a exception at ImpressioneHandler, reason: {}, \n BidContext: \n {}",
						e.getMessage(), impBidContext.toString(), e);
			} finally {
				// FIXME 记录日志，将日志处理放到RequestHandler层
				loggerService.logAdBidRequest(impBidContext);
			}
		}
		long processingTimeMs = System.currentTimeMillis() - besBidRequest.getRequestTimestamp();
		responseBuilder.setProcessingTimeMs((int)processingTimeMs);
		responseBuilder.setDebugString(String.valueOf(bidRequest.getIsTest()));
		return besBidResponse;
	}


	public BidContext initBidData(BidAdRequest bidAdRequest) {
		BidContext bidContext = new BidContext();
		if (bidAdRequest == null)
			return null;
		bidContext.setChannel(bidAdRequest.getChannelID());
		bidContext.setAdxType(Integer.parseInt(Exchange.BES.getValue()));
		bidContext.setRequestTimestamp(System.currentTimeMillis());
		bidContext.setServerId(IPUtils.getHostName());

		BESBidRequest besBidRequest = (BESBidRequest) bidAdRequest;
		BidRequest bidRequest = besBidRequest.buildRequest();
		bidContext.setFeeType("CPM"); //请求中的feeType
		bidContext.setTransactionType(AdViewBidRequest.AT.SECOND.ordinal());//TODO..
		bidContext.setBidId(bidRequest.getId());
		bidContext.setIp(bidRequest.getIp());
		
		bidContext.setUa(bidRequest.getUserAgent());
		this.convertIPDetail(bidContext.getIp(), bidContext);
		
		
		//用户信息 
		bidContext.setUserCategory(bidRequest.getUserCategoryList());
		
		CustomizedUserTag customizedUserTag = bidRequest.getCustomizedUserTag();
		List<Long> usrTgs = new ArrayList<>();
		if(customizedUserTag!=null&&customizedUserTag.getAmsTagListList()!=null){
			List<AmsTag> amsTagListList = customizedUserTag.getAmsTagListList();
			for (AmsTag amsTag : amsTagListList) {
				usrTgs.add(amsTag.getTagId());
			}
		}
		bidContext.setCustomizedUserTags(usrTgs);
		
		// 页面语言
		bidContext.setLanguage(bidRequest.getDetectedLanguage());
		// flash版本
		bidContext.setFlashVersion(bidRequest.getFlashVersion());
		// 位置信息    TODO 为什么有多个坐标。
		Geo geo = bidRequest.getUserGeoInfo();
		List<Coordinate> userCoordinateList = geo.getUserCoordinateList();
		if(userCoordinateList!=null&&userCoordinateList.size()>0){
			Coordinate coordinate = userCoordinateList.get(0);
//			float lati = new BigDecimal(coordinate.getLatitude()).divide(new BigDecimal(1000000)).floatValue();
//			float longitude = new BigDecimal(coordinate.getLongitude()).divide(new BigDecimal(1000000)).floatValue();
			bidContext.setLatitude(coordinate.getLatitude());
			bidContext.setLongitude(coordinate.getLongitude());
		}
		//用户位置信息  UserLocation TODO
		
		//页面信息
		bidContext.setRefUrl(bidRequest.getUrl());
		bidContext.setTopRefUrl(bidRequest.getReferer());
		bidContext.setSiteCategory(bidRequest.getSiteCategory());
		bidContext.setSiteQuality(bidRequest.getSiteQuality());
		bidContext.setPageType(bidRequest.getPageType());
		bidContext.setPageKeyword(bidRequest.getPageKeywordList());
		bidContext.setPageQuality(bidRequest.getPageQuality());
		bidContext.setPageVertical(bidRequest.getPageVertical());
		bidContext.setExcludeIndustryCategory(StringUtil.arrayToCommaDelimitedString(bidRequest.getExcludedProductCategoryList()));
				
		// Device信息
			//移动设备
			Mobile mobile = bidRequest.getMobile();
			//
			//如果多个重复取最后一个。
			List<MobileID> idList = mobile.getIdList();
			for (MobileID mobileID : idList) {
				if(mobileID.getType()==MobileID.IDType.IMEI){
					bidContext.setImei(mobileID.getId());
				}
				if(mobileID.getType()==MobileID.IDType.MAC){
					bidContext.setMac(mobileID.getId());
				}
			}
			//
			int deviceTypeVal = 0;
			MobileDeviceType deviceType = mobile.getDeviceType();
			OS os = mobile.getPlatform();
			if(deviceType==MobileDeviceType.HIGHEND_PHONE){
				if(os==OS.IOS){
					deviceTypeVal=1;
				}else if(os==OS.ANDROID){
					deviceTypeVal=2;
				}else if(os==OS.WINDOWS_PHONE){
					deviceTypeVal=4;
				}else{
					deviceTypeVal=0;
				}
			}
			if(deviceType==MobileDeviceType.TABLET){
				if(os==OS.IOS){
					deviceTypeVal=3;
				}else if(os==OS.ANDROID){
					deviceTypeVal=5;
				}else if(os==OS.WINDOWS_PHONE){
					deviceTypeVal=0;
				}else{
					deviceTypeVal=0;
				}
			}
			bidContext.setDeviceType(deviceTypeVal);
			//
			int osVal = 0;
			if(os==OS.IOS){
				osVal=2;
			}else if(os==OS.ANDROID){
				osVal=1;
			}else if(os==OS.WINDOWS_PHONE){
				osVal=3;
			}else{
				osVal=0;
			}
			bidContext.setOs(osVal);
			//
			DeviceOsVersion osVersion = mobile.getOsVersion();
			StringBuilder stringBuilder = new StringBuilder();
			if(os==OS.ANDROID){
				stringBuilder.append(osVersion.getOsVersionMajor())
				.append(".")
				.append(osVersion.getOsVersionMinor());
			}else{
				stringBuilder.append(osVersion.getOsVersionMajor())
				.append(".")
				.append(osVersion.getOsVersionMinor())
				.append(".")
				.append(osVersion.getOsVersionMicro());
			}
			bidContext.setOsVersion(stringBuilder.toString());
			
			//brand
			bidContext.setBrand(mobile.getBrand());
			//model
			bidContext.setModal(mobile.getModel());
			//
			bidContext.setScreenWidth(mobile.getScreenWidth());
			//
			bidContext.setScreenHeight(mobile.getScreenHeight());
			//screen_density
			bidContext.setScreenDensity(mobile.getScreenDensity());
			//
			Operator operator = AdViewOperator.adViewOperatorMap.get(String.valueOf(mobile.getCarrierId()));
			if(operator!=null){
				bidContext.setMobOps(operator.getValue());
			}
			//
			Connection connection = AdBesConnection.adConnectionMap.get(mobile.getWirelessNetworkType());
			bidContext.setConnType(connection.getValue());
			
			//
			List<ForAdvertisingID> forAdvertisingIdList = mobile.getForAdvertisingIdList();
			if(forAdvertisingIdList!=null){
				for (ForAdvertisingID forAdvertisingID : forAdvertisingIdList) {
					
					if(forAdvertisingID.getType()==ForAdvertisingID.IDType.ANDROID_ID){
						bidContext.setAnid(forAdvertisingID.getId());
					}else if(forAdvertisingID.getType()==ForAdvertisingID.IDType.IDFA){
						bidContext.setIdfa(forAdvertisingID.getId());
					}else if(forAdvertisingID.getType()==ForAdvertisingID.IDType.UNKNOWN){
						bidContext.setMuniqueType(MUniqueType.OTHER.getValue());
						bidContext.setMuniqueId(forAdvertisingID.getId());
					}else{
						
					}
				}
			}
			
			//MuniqueType 设置
			DeviceInfo device = new DeviceInfo();
			device.setIdfa(bidContext.getIdfa());
			device.setAnid(bidContext.getAnid());
			device.setAaid(bidContext.getAaid());
			device.setMac(bidContext.getMac());
			device.setImei(bidContext.getImei());
			device = WebUtils.generateMUniqueId(device);
			if(device.getMuniqueType()!=null){
				bidContext.setMuniqueType(device.getMuniqueType().getValue());
				bidContext.setMuniqueId(device.getMuniqueId());
			}
			//移动应用信息
			MobileApp app = mobile.getMobileApp();
			if (app != null) {
				bidContext.setAppId(app.getAppId());
				bidContext.setAppBundle(app.getAppBundleId());
				List<AppInteractionType> appInteractionTypeList = app.getAppInteractionTypeList();
				List<Integer> _ait = new ArrayList<>();
				for (AppInteractionType appInteractionType2 : appInteractionTypeList) {
					FalconAppInteractionType falconAppInteractionType = AdBesAppInteractionType.adTypeMap.get(appInteractionType2);
					_ait.add(falconAppInteractionType.getValue());
				}
				bidContext.setAppInteractionType(StringUtil.arrayToCommaDelimitedString(_ait));
				
				bidContext.setAppType(String.valueOf(app.getAppCategory()));
				
			}
		
		// 视频流量的媒体信息  
		Video video = bidRequest.getVideo();
		bidContext.setVideoChannelId(video.getChannelIdList());
		bidContext.setVideoContentLength(video.getContentLength());
		bidContext.setVideoTags(video.getTagsList());
		bidContext.setVideoTitle(video.getTitle());

		//广告位信息在handler中填充。
		
		
		
		//other 
		bidContext.setJsEnable(1);//默认为1

		return bidContext;
	}

	void convertIPDetail(String ip, BidContext bidContext) {
		IPDetail ipDetail = null;
		if (!StringUtils.isEmpty(ip)) {
			ipDetail = IPContext.instance().getIPDetail(IPUtils.convertIPToLong(bidContext.getIp()));
			if (ipDetail != null) {
				bidContext.setCountryId(ipDetail.getCountryId());
				bidContext.setStateId(ipDetail.getStateId());
				bidContext.setCityId(ipDetail.getCityId());
				bidContext.setDistrictId(ipDetail.getDistrictId());
			}
		}

//		// ip为空，或者ip异常，解析出错，走地域码的逻辑
//		if (StringUtils.isEmpty(ip) || ipDetail == null) {
//			AreaPlatformMap apm = adService.fetchAreaPlatformMapByTargetId(bidContext.getAreaCode());
//			if (apm != null) {
//				if (apm.getType() == 1)
//					bidContext.setStateId(apm.getAreaId());
//				else if (apm.getType() == 2)
//					bidContext.setCityId(apm.getAreaId());
//			}
//
//		}

	}
	
}
